package com.rename.mips;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.Reader;
import java.util.ArrayList;
import java.util.List;

public class MIPSsim {
	
public static class Disassembly{
		
		// 二进制指令
		private String binary;
		// 地址
		private int address;
		// 指令
		private String instruction;
		// 
		private int rd = -1;
		//
		private int rs = -1;
		//
		private int rt = -1;
		//
		private int immediate;
		//
		private int offset1;
		//
		private int offset2;
		//
		private int base = -1;
		//
		private int sa;
		//
		private int target;
		// 完整指令语句，包括操作数
		private String instruSentence;
		// 种类
		private String category;
		
		public String getBinary() {
			return binary;
		}
		public void setBinary(String binary) {
			this.binary = binary;
		}
		public int getAddress() {
			return address;
		}
		public void setAddress(int address) {
			this.address = address;
		}
		public String getInstruction() {
			return instruction;
		}
		public void setInstruction(String instruction) {
			this.instruction = instruction;
		}
		public int getRd() {
			return rd;
		}
		public void setRd(int rd) {
			this.rd = rd;
		}
		public int getRs() {
			return rs;
		}
		public void setRs(int rs) {
			this.rs = rs;
		}
		public int getRt() {
			return rt;
		}
		public void setRt(int rt) {
			this.rt = rt;
		}
		public int getImmediate() {
			return immediate;
		}
		public void setImmediate(int immediate) {
			this.immediate = immediate;
		}
		public int getOffset1() {
			return offset1;
		}
		public void setOffset1(int offset1) {
			this.offset1 = offset1;
		}
		public int getOffset2() {
			return offset2;
		}
		public void setOffset2(int offset2) {
			this.offset2 = offset2;
		}
		public int getBase() {
			return base;
		}
		public void setBase(int base) {
			this.base = base;
		}
		public int getSa() {
			return sa;
		}
		public void setSa(int sa) {
			this.sa = sa;
		}
		public int getTarget() {
			return target;
		}
		public void setTarget(int target) {
			this.target = target;
		}
		public String getInstruSentence() {
			return instruSentence;
		}
		public void setInstruSentence(String instruSentence) {
			this.instruSentence = instruSentence;
		}
		public String getCategory() {
			return category;
		}
		public void setCategory(String category) {
			this.category = category;
		}
	}

	// 第一种类型指令最高位为0，LW和SW为1
	// 第二种类型中第一小类型指令最高位为0
	// 第二种类型中第二小类型指令最高位为1
	
	/*
	 * 立即数是否有符号
	 * SLL: 无符号
	 * J: 无符号
	 * -----------
	 * BLTZ: 有符号
	 * BEQ: 有符号
	 * BGTZ: 有符号
	 * ADD_2_2: 有符号
	 * SUB_2_2: 有符号
	 * MUL_2_2: 有符号
	 * AND_2_2: 有符号
	 * NOR_2_2: 有符号
	 * SLT_2_2: 有符号
	 */

	// category-1
	private final static String ADD_1 = "100000";
	private final static String BEQ = "000100";
	private final static String BGTZ = "000111";
	private final static String BLTZ = "00000";
	private final static String BREAK = "001101";
	private final static String J = "000010";
	private final static String JR = "001000";
	private final static String NOP = "00000000000000000000000000000000";
	private final static String SLL = "000000";
	private final static String SRL = "000010";
	private final static String SRA = "000011";
	private final static String SUB_1 = "100010";
	private final static String SW = "101011";
	private final static String LW = "100011";

	// category-2.1
	private final static String MUL_2_1 = "000010";
	private final static String AND_2_1 = "100100";
	private final static String NOR_2_1 = "100111";
	private final static String SLT_2_1 = "101010";
	// category-2.2
	private final static String ADD_2_2 = "10000";
	private final static String SUB_2_2 = "10001";
	private final static String MUL_2_2 = "00001";
	private final static String AND_2_2 = "10010";
	private final static String NOR_2_2 = "10011";
	private final static String SLT_2_2 = "10101";

	public static void main(String args[]) {
		// 读取输入文件sample
		final String inputFileName = "sample.txt";
		File inputFile = new File(inputFileName);
		// 如果文件夹不存在则创建
		if (!inputFile.exists()) {
			System.out.println("输入文件不存在！");
			return;
		}
		try {
			System.out.println("sample.txt文件路径：" + new File(inputFileName).getCanonicalPath());
		} catch (IOException e1) {
			e1.printStackTrace();
		}
		// 读取的二进制汇编指令
		List<String> instructionList = readFileByChars(inputFileName);
		System.out.println("sample.txt文件读取完成");

		final String special = "000000";
		final String special2 = "011100";
		final String regimm = "000001";
		boolean isBreak = false; // 判断是否为break指令
		final int startAddr = 64; // 指令开始地址
		int address = startAddr; // 指令地址
		int dataStartAddr = 0; // simulation中data开始地址
		boolean isStart = false; // 是否为开始地址
		List<String> disassemblyList = new ArrayList<String>(); // disassembly结果
		List<String> simulationList = new ArrayList<String>(); // simulation过程
		List<Integer> dataList = new ArrayList<Integer>(); // simulation data
		List<Disassembly> disassembList = new ArrayList<Disassembly>();
		// 寄存器值
		List<Integer> registerValueList = new ArrayList<Integer>();
		for(int k = 0; k < 32; k++){
			registerValueList.add(0);
		}
		
		for(int i = 0; i < instructionList.size(); i++){
			String instruction = instructionList.get(i);
			if (!isBreak) { // 执行break指令之前
				StringBuilder instructionSb = new StringBuilder(instruction);
				instructionSb.insert(6, " ");
				instructionSb.insert(12, " ");
				instructionSb.insert(18, " ");
				instructionSb.insert(24, " ");
				instructionSb.insert(30, " ");
				// disassembly输出
				String out = instructionSb.toString() + "\t" + address + "\t";
				
				// 临时变量
				String temp;
				
				int rs = Integer.parseInt(instruction.substring(6, 11), 2);
				int rt = Integer.parseInt(instruction.substring(11, 16), 2);
				int rd = Integer.parseInt(instruction.substring(16, 21), 2);
				
				// categroy-2.2指令的immediate有符号位
				String immediateStr = instruction.substring(instruction.length() - 16, instruction.length());
				int immediate = calculate(immediateStr);
				
//				String offsetStr = instruction.substring(instruction.length() - 16, instruction.length());
				String offsetStr = instruction.substring(instruction.length() - 16, instruction.length());
				int offset1 = Integer.parseInt(offsetStr, 2);
				// offset2需要左移2位变为18位，BLTZ、BEQ和BGTZ的offset2有符号位
				int offset2 = calculate(offsetStr + "00");
//				int offset2 = calculate("00" + offsetStr);
				System.out.println("00" + offsetStr);
				System.out.println(offset2);
				
				int base = Integer.parseInt(instruction.substring(6, 11), 2);
				int sa = Integer.parseInt(instruction.substring(instruction.length() - 11, instruction.length() - 6), 2);
				
				String targetStr = instruction.substring(instruction.length() - 26, instruction.length());
				// target需要左移2位变为28位
				int target = Integer.parseInt(targetStr + "00", 2);
				
				// 第一位
				char ch = instruction.charAt(0);
				// 前六位
				String first6Bits = instruction.substring(0, 6); // 判断special
				// 后六位
				String last6Bits = instruction.substring(
						instruction.length() - 6, instruction.length());
				// 从第二位开始，前五位
				String second5Bits = instruction.substring(1, 6);

				if (ch == '0') {
					if (NOP.equals(instruction)) { // 指令NOP
						temp = "NOP";
						out += temp;
						
						Disassembly disassemb = new Disassembly();
						disassemb.setBinary(instruction);
						disassemb.setAddress(address);
						disassemb.setInstruction("NOP");
						disassemb.setInstruSentence(temp);
						disassembList.add(disassemb);
					} else if (special.equals(first6Bits)) { // 前6位为special
						if (ADD_1.equals(last6Bits)) {
							temp = "ADD" + "\tR" + rd + "," + " R" + rs + "," + " R" + rt;
							out += temp;
							
							Disassembly disassemb = new Disassembly();
							disassemb.setBinary(instruction);
							disassemb.setAddress(address);
							disassemb.setInstruction("ADD_1");
							disassemb.setInstruSentence(temp);
							disassemb.setRd(rd);
							disassemb.setRs(rs);
							disassemb.setRt(rt);
							disassembList.add(disassemb);
						} else if (JR.equals(last6Bits)) {
//							temp = "JR" + " R" + rs;
							temp = "JR" + "\tR" + rs;
							out += temp;
							
							Disassembly disassemb = new Disassembly();
							disassemb.setBinary(instruction);
							disassemb.setAddress(address);
							disassemb.setInstruction("JR");
							disassemb.setInstruSentence(temp);
							disassemb.setRs(rs);
							disassembList.add(disassemb);
						} else if (BREAK.equals(last6Bits)) {
							temp = "BREAK";
							out += temp;
							
							isBreak = true;
							isStart = true;
							
							Disassembly disassemb = new Disassembly();
							disassemb.setBinary(instruction);
							disassemb.setAddress(address);
							disassemb.setInstruction("BREAK");
							disassemb.setInstruSentence(temp);
							disassembList.add(disassemb);
						} else if (SLL.equals(last6Bits)) {
							temp = "SLL" + "\tR" + rd + "," + " R" + rt + "," + " #" + sa;
							out += temp;
							
							Disassembly disassemb = new Disassembly();
							disassemb.setBinary(instruction);
							disassemb.setAddress(address);
							disassemb.setInstruction("SLL");
							disassemb.setInstruSentence(temp);
							disassemb.setRd(rd);
							disassemb.setRt(rt);
							disassemb.setSa(sa);
							disassembList.add(disassemb);
						} else if (SRA.equals(last6Bits)) {
							temp = "SRA" + "\tR" + rd + "," + " R" + rt + "," + " #" + sa;
							out += temp;
							
							Disassembly disassemb = new Disassembly();
							disassemb.setBinary(instruction);
							disassemb.setAddress(address);
							disassemb.setInstruction("SRA");
							disassemb.setInstruSentence(temp);
							disassemb.setRd(rd);
							disassemb.setRt(rt);
							disassemb.setSa(sa);
							disassembList.add(disassemb);
						} else if (SRL.equals(last6Bits)) {
							temp = "SRL" + "\tR" + rd + "," + " R" + rt + "," + " #" + sa;
							out += temp;
							
							Disassembly disassemb = new Disassembly();
							disassemb.setBinary(instruction);
							disassemb.setAddress(address);
							disassemb.setInstruction("SRL");
							disassemb.setInstruSentence(temp);
							disassemb.setRd(rd);
							disassemb.setRt(rt);
							disassemb.setSa(sa);
							disassembList.add(disassemb);
						} else if (SUB_1.equals(last6Bits)) {
							temp = "SUB" + "\tR" + rd + "," + " R" + rs + "," + " R" + rt;
							out += temp;
							
							Disassembly disassemb = new Disassembly();
							disassemb.setBinary(instruction);
							disassemb.setAddress(address);
							disassemb.setInstruction("SUB_1");
							disassemb.setInstruSentence(temp);
							disassemb.setRd(rd);
							disassemb.setRs(rs);
							disassemb.setRt(rt);
							disassembList.add(disassemb);
						} else if (AND_2_1.equals(last6Bits)) {
							temp = "AND" + "\tR" + rd + "," + " R" + rs + "," + " R" + rt;
							out += temp;
							
							Disassembly disassemb = new Disassembly();
							disassemb.setBinary(instruction);
							disassemb.setAddress(address);
							disassemb.setInstruction("AND_2_1");
							disassemb.setInstruSentence(temp);
							disassemb.setRd(rd);
							disassemb.setRs(rs);
							disassemb.setRt(rt);
							disassembList.add(disassemb);
						} else if (NOR_2_1.equals(last6Bits)) {
							temp = "NOR" + "\tR" + rd + "," + " R" + rs + "," + " R" + rt;
							out += temp;
							
							Disassembly disassemb = new Disassembly();
							disassemb.setBinary(instruction);
							disassemb.setAddress(address);
							disassemb.setInstruction("NOR_2_1");
							disassemb.setInstruSentence(temp);
							disassemb.setRd(rd);
							disassemb.setRs(rs);
							disassemb.setRt(rt);
							disassembList.add(disassemb);
						} else if (SLT_2_1.equals(last6Bits)) {
							temp = "SLT" + "\tR" + rd + "," + " R" + rs + "," + " R" + rt;
							out += temp;
							
							Disassembly disassemb = new Disassembly();
							disassemb.setBinary(instruction);
							disassemb.setAddress(address);
							disassemb.setInstruction("SLT_2_1");
							disassemb.setInstruSentence(temp);
							disassemb.setRd(rd);
							disassemb.setRs(rs);
							disassemb.setRt(rt);
							disassembList.add(disassemb);
						}
					} else if (special2.equals(first6Bits)) { // 前6位为special2
						if (MUL_2_1.equals(last6Bits)) {
							temp = "MUL" + "\tR" + rd + "," + " R" + rs + "," + " R" + rt;
							out += temp;
							
							Disassembly disassemb = new Disassembly();
							disassemb.setBinary(instruction);
							disassemb.setAddress(address);
							disassemb.setInstruction("MUL_2_1");
							disassemb.setInstruSentence(temp);
							disassemb.setRd(rd);
							disassemb.setRs(rs);
							disassemb.setRt(rt);
							disassembList.add(disassemb);
						}
					} else if (regimm.equals(first6Bits)) { // 前6位为regimm
						String s = instruction.substring(11, 16);
						if (BLTZ.equals(s)) {
//							temp = "BLTZ" + " R" + rs + "," + " #" + offset2;
							temp = "BLTZ" + "\tR" + rs + "," + " #" + offset2;
							out += temp;
							
							Disassembly disassemb = new Disassembly();
							disassemb.setBinary(instruction);
							disassemb.setAddress(address);
							disassemb.setInstruction("BLTZ");
							disassemb.setInstruSentence(temp);
							disassemb.setRs(rs);
							disassemb.setOffset2(offset2);
							disassembList.add(disassemb);
						}
					} else if (BEQ.equals(first6Bits)) { // 前6位为指令码
//						temp = "BEQ" + " R" + rs + "," + " R" + rt + "," + " #" + offset2;
						temp = "BEQ" + "\tR" + rs + "," + " R" + rt + "," + " #" + offset2;
						out += temp;
						
						Disassembly disassemb = new Disassembly();
						disassemb.setBinary(instruction);
						disassemb.setAddress(address);
						disassemb.setInstruction("BEQ");
						disassemb.setInstruSentence(temp);
						disassemb.setRs(rs);
						disassemb.setRt(rt);
						disassemb.setOffset2(offset2);
						disassembList.add(disassemb);
					} else if (BGTZ.equals(first6Bits)) { // 前6位为指令码
//						temp = "BGTZ" + " R" + rs + "," + " #" + offset2;
						temp = "BGTZ" + "\tR" + rs + "," + " #" + offset2;
						out += temp;
						
						Disassembly disassemb = new Disassembly();
						disassemb.setBinary(instruction);
						disassemb.setAddress(address);
						disassemb.setInstruction("BGTZ");
						disassemb.setInstruSentence(temp);
						disassemb.setRs(rs);
						disassemb.setOffset2(offset2);
						disassembList.add(disassemb);
					} else if (J.equals(first6Bits)) { // 前6位为指令码
//						temp = "J" + " #" + target;
						temp = "J" + "\t#" + target;
						out += temp;
						
						Disassembly disassemb = new Disassembly();
						disassemb.setBinary(instruction);
						disassemb.setAddress(address);
						disassemb.setInstruction("J");
						disassemb.setInstruSentence(temp);
						disassemb.setTarget(target);
						disassembList.add(disassemb);
					}
				} else {
					if (LW.equals(first6Bits)) { // 指令LW
						temp = "LW" + "\tR" + rt + "," + " " + offset1 + "(R" + base + ")";
						out += temp;
						
						Disassembly disassemb = new Disassembly();
						disassemb.setBinary(instruction);
						disassemb.setAddress(address);
						disassemb.setInstruction("LW");
						disassemb.setInstruSentence(temp);
						disassemb.setRt(rt);
						disassemb.setOffset1(offset1);
						disassemb.setBase(base);
						disassembList.add(disassemb);
						
					} else if (SW.equals(first6Bits)) { // 指令SW
						temp = "SW" + "\tR" + rt + "," + " " + offset1 + "(R" + base + ")";
						out += temp;
						
						Disassembly disassemb = new Disassembly();
						disassemb.setBinary(instruction);
						disassemb.setAddress(address);
						disassemb.setInstruction("SW");
						disassemb.setInstruSentence(temp);
						disassemb.setRt(rt);
						disassemb.setOffset1(offset1);
						disassemb.setBase(base);
						disassembList.add(disassemb);
					} else { // 指令2.2
						if (ADD_2_2.equals(second5Bits)) {
							temp = "ADD" + "\tR" + rt + "," + " R" + rs + "," + " #" + immediate;
							out += temp;
							
							Disassembly disassemb = new Disassembly();
							disassemb.setBinary(instruction);
							disassemb.setAddress(address);
							disassemb.setInstruction("ADD_2_2");
							disassemb.setInstruSentence(temp);
							disassemb.setRt(rt);
							disassemb.setRs(rs);
							disassemb.setImmediate(immediate);
							disassembList.add(disassemb);
						} else if (SUB_2_2.equals(second5Bits)) {
							temp = "SUB" + "\tR" + rt + "," + " R" + rs + "," + " #" + immediate;
							out += temp;
							
							Disassembly disassemb = new Disassembly();
							disassemb.setBinary(instruction);
							disassemb.setAddress(address);
							disassemb.setInstruction("SUB_2_2");
							disassemb.setInstruSentence(temp);
							disassemb.setRt(rt);
							disassemb.setRs(rs);
							disassemb.setImmediate(immediate);
							disassembList.add(disassemb);
						} else if (MUL_2_2.equals(second5Bits)) {
							temp = "MUL" + "\tR" + rt + "," + " R" + rs + "," + " #" + immediate;
							out += temp;
							
							Disassembly disassemb = new Disassembly();
							disassemb.setBinary(instruction);
							disassemb.setAddress(address);
							disassemb.setInstruction("MUL_2_2");
							disassemb.setInstruSentence(temp);
							disassemb.setRt(rt);
							disassemb.setRs(rs);
							disassemb.setImmediate(immediate);
							disassembList.add(disassemb);
						} else if (AND_2_2.equals(second5Bits)) {
							temp = "AND" + "\tR" + rt + "," + " R" + rs + "," + " #" + immediate;
							out += temp;
							
							Disassembly disassemb = new Disassembly();
							disassemb.setBinary(instruction);
							disassemb.setAddress(address);
							disassemb.setInstruction("AND_2_2");
							disassemb.setInstruSentence(temp);
							disassemb.setRt(rt);
							disassemb.setRs(rs);
							disassemb.setImmediate(immediate);
							disassembList.add(disassemb);
						} else if (NOR_2_2.equals(second5Bits)) {
							temp = "NOR" + "\tR" + rt + "," + " R" + rs + "," + " #" + immediate;
							out += temp;
							
							Disassembly disassemb = new Disassembly();
							disassemb.setBinary(instruction);
							disassemb.setAddress(address);
							disassemb.setInstruction("NOR_2_2");
							disassemb.setInstruSentence(temp);
							disassemb.setRt(rt);
							disassemb.setRs(rs);
							disassemb.setImmediate(immediate);
							disassembList.add(disassemb);
						} else if (SLT_2_2.equals(second5Bits)) {
							temp = "SLT" + "\tR" + rt + "," + " R" + rs + "," + " #" + immediate;
							out += temp;
							
							Disassembly disassemb = new Disassembly();
							disassemb.setBinary(instruction);
							disassemb.setAddress(address);
							disassemb.setInstruction("SLT_2_2");
							disassemb.setInstruSentence(temp);
							disassemb.setRt(rt);
							disassemb.setRs(rs);
							disassemb.setImmediate(immediate);
							disassembList.add(disassemb);
						}
					}
				}
				disassemblyList.add(out);
			} else { // 执行BREAK指令后，读取memory中的数据
				if(isStart){
					dataStartAddr = address;
					isStart = false;
				}
				String out = "";
				// break指令之后的二进制数据求补码
				String complement = toComplement(instruction);
				int result = calculate(complement);
				out = instruction + "\t" + address + "\t" + result;
				disassemblyList.add(out);
				dataList.add(result);
			}
			address += 4;
		}
		
		// 结果输出到文件disassembly.txt
		final String outFileName = "disassembly.txt";
		try {
			if(createFile(new File(outFileName))){
				writeTxtFile(disassemblyList, outFileName);
				System.out.println("disassembly.txt文件输出完成");
				System.out.println("disassembly.txt文件路径：" + new File(outFileName).getCanonicalPath());
			}
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		// 执行指令
		simulationList = excute(registerValueList, disassembList, dataList, dataStartAddr, startAddr);	
		
		// 运行过程输出到文件simulation.txt
		final String outFileName2 = "simulation.txt";
		try {
			if(createFile(new File(outFileName2))){
				writeTxtFile(simulationList, outFileName2);
				System.out.println("simulation.txt文件输出完成");
				System.out.println("simulation.txt文件路径：" + new File(outFileName2).getCanonicalPath());
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 批量执行指令，返回执行过程
	 * @param registerValueList 寄存器值
	 * @param disassembList 指令
	 * @param dataList 数据
	 * @param dataStartAddr 数据开始地址
	 * @param startAddr 指令开始地址
	 * @return
	 */
	public static List<String> excute(List<Integer> registerValueList, List<Disassembly> disassembList, List<Integer> dataList, int dataStartAddr, int startAddr){
		
		List<String> simulationList = new ArrayList<String>();
		int cycleCount = 0;
		String temp;
		boolean isBreak = false;
		
		// IF Unit,0:Waiting Instruction,1:Executed Instruction
		Disassembly[] if_Unit =  new Disassembly[2];
		// Pre-Issue Buffer 4
		Disassembly[] pre_Issue_Buffer =  new Disassembly[4];
		// Pre-ALU Queue 2
		Disassembly[] pre_ALU_Queue =  new Disassembly[2];
		// Post-ALU Buffer 1
		Disassembly post_ALU_Buffer = null;
		// Pre-ALUB Queue 2
		Disassembly[] pre_ALUB_Queue =  new Disassembly[2];
		// Post-ALUB Buffer 1
		Disassembly post_ALUB_Buffer = null;
		// Pre-MEM Queue 2
		Disassembly[] pre_MEM_Queue =  new Disassembly[2];
		// Post-MEM Buffer 1
		Disassembly post_MEM_Buffer = null;
		
		/* 所有指令从Queue或者Buffer中移除都是在功能单元操作之前的一个周期进行
		 * 
		 * 1.一次可以提取最多2条指令
		 * 2.如果buffer中只有一个空则只可以提取一条指令
		 * 3.如果提取单元停顿了，那么当前周期就不能提取指令了（分支指令会造成提取单元停顿）
		 * 4.如果分支指令所需的寄存器或者内存可获得则更新PC，否则将会造成停顿直到寄存器或者内存是可获得的
		 * 5.如果提取了两条指令第一天是分支指令，那么需要将第二条指令丢弃
		 * 6.寄存器访问是同步的
		 * 7.功能单元不能读取在相同周期写入（WB）的新的寄存器值
		 * 8.如果提取到了BREAK指令（不管是第一条还是第二条）就停止模拟
		 * 9.BREAK指令和NOP指令不写入Pre-Issue Buffer，但是要保证提取之前的一个周期Pre-Issue Buffer有空闲的地方存放它们
		 * 
		 * 1.Pre-issue Buffer位置0永远放最旧的指令，3永远放最新的指令
		 * 
		 * 1.每个周期最多发射2个指令（乱序），一个指令发射之后，就要在当前周期结束之前从Pre-issue Buffer中移除
		 * 2.按0-3顺序检索Pre-issue Buffer，发射指令前要保证没有结构冒险、没有WAW冒险、没有WAR冒险、内存访问指令保证所有源寄存器可用、加载指令保证之前的存储已发射，存储必须按序发射
		 * 
		 * 1.Pre-ALU queue遵循先进先出
		 * 
		 * 1.ALU处理所有非内存指令除了SLL, SRL, SRA和MUL
		 * 2.所有指令在ALU中需要花费一个周期
		 * 3.Post-ALU buffer不需要检查结构冒险
		 * 
		 * 1.Pre-ALUB queue遵循先进先出
		 * 
		 * 1.ALUB处理SLL, SRL, SRA and MUL.
		 * 2.所有指令在ALUB中需要花费两个周期
		 * 3.在周期N+2处理完指令，那么在周期N+2就需要写入Post-ALUB buffer
		 * 
		 * 1.MEM单元只处理LW和SW指令，花费一个周期，执行玩之后立即写入Post-MEM buffer
		 * 
		 * 1.WB单元在一个周期中可以执行3个写回，基于Post-ALU Buffer, Post-ALUB Buffer, and Post-MEM Buffer更新寄存器值，下个周期就可以获取新值
		 * 
		 * 1.PC记录下一条待提取的指令的地址，初始位置为64
		 * 
		 * a. NOP, Branch, BREAK: only IF;
		 * b. SW: IF, Issue, MEM;
		 * c. LW: IF, Issue, MEM, WB;
		 * d. SLL, SRL ,SRA and MUL: IF, Issue, ALUB, WB
		 * e. Other instructions: IF, Issue, ALU, WB.
		 */
		
		int post_AlUB_cycle = 0;
		for(int i = 0; i < disassembList.size(); i++){
			
			// 临时变量
			// IF Unit,0:Waiting Instruction,1:Executed Instruction
			Disassembly[] if_Unit_temp = if_Unit.clone();
			// Pre-Issue Buffer 4
			Disassembly[] pre_Issue_Buffer_temp = pre_Issue_Buffer.clone();
			// Pre-ALU Queue 2
			Disassembly[] pre_ALU_Queue_temp = pre_ALU_Queue.clone();
			// Post-ALU Buffer 1
			Disassembly post_ALU_Buffer_temp = cloneDisassembly(post_ALU_Buffer);
			// Pre-ALUB Queue 2
			Disassembly[] pre_ALUB_Queue_temp = pre_ALUB_Queue.clone();
			// Post-ALUB Buffer 1
			Disassembly post_ALUB_Buffer_temp = cloneDisassembly(post_ALUB_Buffer);
			// Pre-MEM Queue 2
			Disassembly[] pre_MEM_Queue_temp = pre_MEM_Queue.clone();
			// Post-MEM Buffer 1
			Disassembly post_MEM_Buffer_temp = cloneDisassembly(post_MEM_Buffer);
			
			/* IF
			 * 1.一次可以提取最多2条指令
			 * 2.如果buffer中只有一个空则只可以提取一条指令
			 * 3.如果提取单元停顿了，那么当前周期就不能提取指令了（分支指令会造成提取单元停顿）
			 * 4.如果分支指令所需的寄存器或者内存可获得则更新PC，否则将会造成停顿直到寄存器或者内存是可获得的
			 * 5.如果提取了两条指令第一条是分支指令，那么需要将第二条指令丢弃
			 * 6.寄存器访问是同步的
			 * 7.功能单元不能读取在相同周期写入（WB）的新的寄存器值
			 * 8.如果提取到了BREAK指令（不管是第一条还是第二条）就停止模拟
			 * 9.BREAK指令和NOP指令不写入Pre-Issue Buffer，但是要保证提取之前的一个周期Pre-Issue Buffer有空闲的地方存放它们
			 */			
			if(if_Unit[1] != null){
				int rs = if_Unit[1].getRs();
				int rt = if_Unit[1].getRt();
				int address = if_Unit[1].getAddress();
				int offset2 = if_Unit[1].getOffset2();
				int target = if_Unit[1].getTarget();
				if("BEQ".equals(if_Unit[1].getInstruction())){
					// 如果rs==rt，跳转到地址为((address+4)+offset2)的指令，即相对于当前(address+4)进行offset2的偏移
					if(registerValueList.get(rs) == registerValueList.get(rt)){
						i = ((address + 4) + offset2 - startAddr) / 4; 
					}
				}else if("BGTZ".equals(if_Unit[1].getInstruction())){
					// 如果rs>0，跳转到地址为((address+4)+offset2)的指令，即相对于当前(address+4)进行offset2的偏移
					if(registerValueList.get(rs) > 0){
						i = ((address + 4) + offset2 - startAddr) / 4; 
					}
				}else if("BLTZ".equals(if_Unit[1].getInstruction())){
					// 如果rs<0，跳转到地址为((address+4)+offset2)的指令，即相对于当前(address+4)进行offset2的偏移
					if(registerValueList.get(rs) < 0){
						i = ((address + 4) + offset2 - startAddr) / 4; 
					}
				}else if("J".equals(if_Unit[1].getInstruction())){
					// 无条件转移，目的地址为target
					i = (target - startAddr) / 4; 
				}else if("JR".equals(if_Unit[1].getInstruction())){
					// 无条件转移，目的地址为rs
					i = (registerValueList.get(rs) - startAddr) / 4; 
				}
				if_Unit_temp[1] = null;
			}
			int instruCount = 0; // 提取的指令个数
			int firstIndex = 0; // 最近第一条被提取的指令在buffer中的索引
			// pre_Issue_Buffer有空闲的位置才能提取指令
			if(null == if_Unit_temp[0]){ // 没有分支指令
				for(int j = 0; j < pre_Issue_Buffer.length; j++){
					if(instruCount < 2){ // 最多两条
						// 要么连续放两条，要么只能放一条，要么一条也放不了
						if(pre_Issue_Buffer[j] == null){
							pre_Issue_Buffer_temp[j] = disassembList.get(i);
							instruCount++;
							firstIndex = j;
							// 只有提取完第一条指令，才能提取第二条指令
							// 判断pre_Issue_Buffer是否还有位置存放指令
							if(i < disassembList.size() - 1 && j < pre_Issue_Buffer.length - 1 && pre_Issue_Buffer[j + 1] == null){
								pre_Issue_Buffer_temp[j + 1] = disassembList.get(i + 1);
								instruCount++;
							}
							// 指令提取结束，跳出循环
							break;
						}
					}else{
						break;
					}
				}	
			}
			// 检查提取的指令中是否有break指令
			if(instruCount > 0){
				if("BREAK".equals(pre_Issue_Buffer_temp[firstIndex].getInstruction()) 
						|| (instruCount == 2 && "BREAK".equals(pre_Issue_Buffer_temp[firstIndex + 1].getInstruction()))){
					isBreak = true;
					if("BREAK".equals(pre_Issue_Buffer_temp[firstIndex].getInstruction())){
						if_Unit_temp[1] = pre_Issue_Buffer_temp[firstIndex];
					}else{
						if_Unit_temp[1] = pre_Issue_Buffer_temp[firstIndex + 1];
					}
					System.out.println("break");
					/*
					 * 整个过程输出信息整合
					 */
					// 周期数
					cycleCount++;
					// simulation输出
					String cycleOut = "--------------------" + "\r\n" + "Cycle:" + cycleCount + "\r\n\r\n";
					// 中间过程
					cycleOut += process(if_Unit_temp, pre_Issue_Buffer_temp, pre_ALU_Queue_temp, post_ALU_Buffer_temp, pre_ALUB_Queue_temp, post_ALUB_Buffer_temp, pre_MEM_Queue_temp, post_MEM_Buffer_temp);
					// 寄存器
					cycleOut += registerOut(registerValueList);
					// 存储器
					cycleOut += memOut(dataStartAddr, dataList);				
					// 添加一个周期输出
					simulationList.add(cycleOut);
					break;
				}else if("NOP".equals(pre_Issue_Buffer_temp[firstIndex].getInstruction()) 
						|| (instruCount == 2 && "NOP".equals(pre_Issue_Buffer_temp[firstIndex + 1].getInstruction()))){
					if(pre_Issue_Buffer_temp[firstIndex] != null){
						if_Unit_temp[1] = pre_Issue_Buffer_temp[firstIndex];
					}else{
						if_Unit_temp[1] = pre_Issue_Buffer_temp[firstIndex + 1];
					}
				}
				if(instruCount == 1 && isBranchInstru(pre_Issue_Buffer_temp[firstIndex].getInstruction())){ // 提取了一条指令为分支指令
					if_Unit_temp[0] = pre_Issue_Buffer_temp[firstIndex];
					pre_Issue_Buffer_temp[firstIndex] = null;
				}else if(instruCount == 2){ // 提取了两条指令
					if(isBranchInstru(pre_Issue_Buffer_temp[firstIndex].getInstruction())){ // 第一条为分支指令
						if_Unit_temp[0] = pre_Issue_Buffer_temp[firstIndex];
						pre_Issue_Buffer_temp[firstIndex] = null;
						pre_Issue_Buffer_temp[firstIndex + 1] = null;
						instruCount--;	
					}else if(isBranchInstru(pre_Issue_Buffer_temp[firstIndex + 1].getInstruction())){ // 第二条为分支指令
						if_Unit_temp[0] = pre_Issue_Buffer_temp[firstIndex + 1];
						pre_Issue_Buffer_temp[firstIndex + 1] = null;
					}
				}
			}
			// NOP、分支指令（J, JR, BEQ, BLTZ)）和BREAK提取后放在Waiting Instruction中，执行完成放在Executed Instruction中
			boolean regSynchronizedFlag2 = true;
			if(if_Unit_temp[0] != null && isBranchInstru(if_Unit_temp[0].getInstruction())){
				regSynchronizedFlag2 = checkRegSynchronized2(if_Unit_temp[0], pre_Issue_Buffer_temp, pre_ALU_Queue_temp, post_ALU_Buffer_temp, pre_ALUB_Queue_temp, post_ALUB_Buffer_temp, pre_MEM_Queue_temp, post_MEM_Buffer_temp);	
			}
			if(regSynchronizedFlag2){
				if_Unit_temp[1] = if_Unit_temp[0];
				if_Unit_temp[0] = null;
			}
			// 如果实际提取了两条指令
			if(instruCount == 2){
				i++;
			}else if(instruCount == 0){ // 如果一条指令也没提取
				i--;
			}
			
			/* Issue
			 * 从pre_Issue_Buffer移动到pre_ALU_Queue/pre_ALUB_Queue/pre_MEM_Queue
			 * 1.每个周期最多发射2个指令（乱序），一个指令发射之后，就要在当前周期结束之前从Pre-issue Buffer中移除
			 * 2.按0-3顺序检索Pre-issue Buffer，发射指令前要保证没有结构冒险、没有WAW冒险、没有WAR冒险、
			 *	内存访问指令保证所有源寄存器可用、加载指令保证之前的存储已发射，存储必须按序发射
			 */
			int issueCount = 0; // 发射的条数
			int instruType = -1; // 指令类型
			for (int j = 0; j < pre_Issue_Buffer.length; j++) {
				if (issueCount < 2) {
					if (pre_Issue_Buffer[j] != null) {
						// TODO 检查结构冒险
						// TODO 检查WAW冒险
						// TODO 检查WAR冒险
						// TODO
						// 检查寄存器访问同步，如果需要与之前的指令访问同一个寄存器，那么需要等到之前的指令WB之后的一个周期才可以访问
						boolean regSynchronizedFlag = true;
						// 检查pre_Issue_Buffer中的指令
						for (int k = 0; k < j; k++) {
							regSynchronizedFlag = checkRegSynchronized(
									pre_Issue_Buffer[j], pre_Issue_Buffer[k]);
							if (!regSynchronizedFlag) {
								break;
							}
						}
						if (regSynchronizedFlag) {
							// 检查非pre_Issue_Buffer中的指令
							regSynchronizedFlag = checkRegSynchronized(
									pre_Issue_Buffer[j], pre_ALU_Queue_temp,
									post_ALU_Buffer_temp, pre_ALUB_Queue_temp,
									post_ALUB_Buffer_temp, pre_MEM_Queue_temp,
									post_MEM_Buffer_temp);
						}

						// 检查通过
						if (regSynchronizedFlag) {
							instruType = toInstruType(pre_Issue_Buffer[j]
									.getInstruction());
							if (instruType == 0) { // ALU指令
								// 判断pre_ALU_Queue是否有空位置
								if (pre_ALU_Queue_temp[0] == null) {
									pre_ALU_Queue_temp[0] = pre_Issue_Buffer[j];
									pre_Issue_Buffer_temp[j] = null;
									issueCount++;
								} else if (pre_ALU_Queue_temp[1] == null) {
									pre_ALU_Queue_temp[1] = pre_Issue_Buffer[j];
									pre_Issue_Buffer_temp[j] = null;
									issueCount++;
								}
							} else if (instruType == 1) { // ALUB指令
								// 判断pre_ALUB_Queue是否有空位置
								if (pre_ALUB_Queue_temp[0] == null) {
									pre_ALUB_Queue_temp[0] = pre_Issue_Buffer[j];
									pre_Issue_Buffer_temp[j] = null;
									issueCount++;
								} else if (pre_ALUB_Queue_temp[1] == null) {
									pre_ALUB_Queue_temp[1] = pre_Issue_Buffer[j];
									pre_Issue_Buffer_temp[j] = null;
									issueCount++;
								}
							} else if (instruType == 2) { // MEM指令
								// TODO 内存访问指令保证所有源寄存器可用
								// TODO 加载指令保证之前的存储已发射
								// TODO 存储必须按序发射,加载指令保证之前的存储已发射
								boolean storeInOrderFlag = true;
								for (int k = 0; k < j; k++) { // 检查前面是否有SW未发射
									if("SW".equals(pre_Issue_Buffer_temp[k])){
										storeInOrderFlag = false;
										break;
									}
								}

								if(storeInOrderFlag){
									// 判断pre_MEM_Queue是否有空位置
									if (pre_MEM_Queue_temp[0] == null) {
										pre_MEM_Queue_temp[0] = pre_Issue_Buffer[j];
										pre_Issue_Buffer_temp[j] = null;
										issueCount++;
									} else if (pre_MEM_Queue_temp[1] == null) {
										pre_MEM_Queue_temp[1] = pre_Issue_Buffer[j];
										pre_Issue_Buffer_temp[j] = null;
										issueCount++;
									}	
								}
							}
						}
					}
				} else {
					break;
				}
			}
			// 发射完，调整pre_Issue_Buffer中剩余指令的位置，0放最旧的
			adjustPosition(pre_Issue_Buffer_temp);
			
			/* WB(ALU/ALUB/MEM指令)
			 * 1.ALU处理其他的指令
			 * 2.ALUB处理SLL, SRL, SRA and MUL.
			 * 3.MEM只处理LW和SW
			 */
			if(post_ALU_Buffer != null){ // ALU
				int rd = post_ALU_Buffer.getRd();
				int rs = post_ALU_Buffer.getRs();
				int rt = post_ALU_Buffer.getRt();
				int offset2 = post_ALU_Buffer.getOffset2();
				int immediate = post_ALU_Buffer.getImmediate();
				int address = post_ALU_Buffer.getAddress();
				int target = post_ALU_Buffer.getTarget();
				
				if("ADD_1".equals(post_ALU_Buffer.getInstruction())){
					// rd<-rs+rt
					registerValueList.set(rd, registerValueList.get(rs) + registerValueList.get(rt));
					
				}else if("BEQ".equals(post_ALU_Buffer.getInstruction())){
					// 如果rs==rt，跳转到地址为((address+4)+offset2)的指令，即相对于当前(address+4)进行offset2的偏移
					if(registerValueList.get(rs) == registerValueList.get(rt)){
						i = ((address + 4) + offset2 - startAddr) / 4; 
						i--; // 下次循环i会加1，所以这里先减1
					}
					
				}else if("BGTZ".equals(post_ALU_Buffer.getInstruction())){
					// 如果rs>0，跳转到地址为((address+4)+offset2)的指令，即相对于当前(address+4)进行offset2的偏移
					if(registerValueList.get(rs) > 0){
						i = ((address + 4) + offset2 - startAddr) / 4; 
						i--; // 下次循环i会加1，所以这里先减1
					}
					
				}else if("BLTZ".equals(post_ALU_Buffer.getInstruction())){
					// 如果rs<0，跳转到地址为((address+4)+offset2)的指令，即相对于当前(address+4)进行offset2的偏移
					if(registerValueList.get(rs) < 0){
						i = ((address + 4) + offset2 - startAddr) / 4; 
						i--; // 下次循环i会加1，所以这里先减1
					}
					
				}else if("BREAK".equals(post_ALU_Buffer.getInstruction())){
					// 停止运行
					isBreak = true;
				}else if("J".equals(post_ALU_Buffer.getInstruction())){
					// 无条件转移，目的地址为target
					i = (target - startAddr) / 4; 
					i--; // 下次循环i会加1，所以这里先减1
					
				}else if("JR".equals(post_ALU_Buffer.getInstruction())){
					// 无条件转移，目的地址为rs
					i = (registerValueList.get(rs) - startAddr) / 4; 
					i--; // 下次循环i会加1，所以这里先减1
					
				}else if("NOP".equals(post_ALU_Buffer.getInstruction())){
					// 无操作
					// ...
				}else if("SUB_1".equals(post_ALU_Buffer.getInstruction())){
					// 减法，rd<-rs-rt
					registerValueList.set(rd, registerValueList.get(rs) - registerValueList.get(rt));
					
				}else if("AND_2_1".equals(post_ALU_Buffer.getInstruction())){
					// 逻辑运算&
					registerValueList.set(rd, registerValueList.get(rs) & registerValueList.get(rt));
					
				}else if("NOR_2_1".equals(post_ALU_Buffer.getInstruction())){
					// 逻辑运算~(rs | rt)
					registerValueList.set(rd, ~(registerValueList.get(rs) | registerValueList.get(rt)));
					
				}else if("SLT_2_1".equals(post_ALU_Buffer.getInstruction())){
					// 如果rs<rt，rd=1，否则rd=0；rd<-(rs < rt)
					if(registerValueList.get(rs) < registerValueList.get(rt)){
						registerValueList.set(rd, 1);
					}else{
						registerValueList.set(rd, 0);
					}
					
				}else if("ADD_2_2".equals(post_ALU_Buffer.getInstruction())){
					// 加法，rt<-rs+immediate
					registerValueList.set(rt, registerValueList.get(rs) + immediate);
					
				}else if("SUB_2_2".equals(post_ALU_Buffer.getInstruction())){
					// 减法，rt<-rs-immediate
					registerValueList.set(rt, registerValueList.get(rs) - immediate);
					
				}else if("AND_2_2".equals(post_ALU_Buffer.getInstruction())){
					// 逻辑运算&
					registerValueList.set(rt, registerValueList.get(rs) & immediate);
					
				}else if("NOR_2_2".equals(post_ALU_Buffer.getInstruction())){
					// 逻辑运算~(rs | rt)
					registerValueList.set(rt, ~(registerValueList.get(rs) | immediate));
					
				}else if("SLT_2_2".equals(post_ALU_Buffer.getInstruction())){
					// 如果rs<iimmediate，rt=1，否则rt=0；rt<-(rs < immediate)
					if(registerValueList.get(rs) < immediate){
						registerValueList.set(rt, 1);
					}else{
						registerValueList.set(rt, 0);
					}
					
				}
				// WB之后，将post_ALU_Buffer置空
				post_ALU_Buffer_temp = null;
			}else if(post_ALUB_Buffer != null){ // ALUB
				int rd = post_ALUB_Buffer.getRd();
				int rs = post_ALUB_Buffer.getRs();
				int rt = post_ALUB_Buffer.getRt();
				int sa = post_ALUB_Buffer.getSa();
				int immediate = post_ALUB_Buffer.getImmediate();
				
				if("SLL".equals(post_ALUB_Buffer.getInstruction())){
					// 执行指令，逻辑左移sa位，rd<-rt<<sa
					registerValueList.set(rd, registerValueList.get(rt) << sa);
					
				}else if("SRL".equals(post_ALUB_Buffer.getInstruction())){
					// 执行指令，逻辑右移sa位，rd<-rt>>sa
					registerValueList.set(rd, registerValueList.get(rt) >> sa); 
					
				}else if("SRA".equals(post_ALUB_Buffer.getInstruction())){
					// 执行指令，算术右移sa位，rd<-rt>>sa，是否要注意符号位？？？
					registerValueList.set(rd, registerValueList.get(rt) >> sa); 
					
				}else if("MUL_2_1".equals(post_ALUB_Buffer.getInstruction())){
					// 乘法 ，rd<-rs*rt
					registerValueList.set(rd, registerValueList.get(rs) * registerValueList.get(rt));
					
				}else if("MUL_2_2".equals(post_ALUB_Buffer.getInstruction())){
					// 乘法，rt<-rs*immediate
					registerValueList.set(rt, registerValueList.get(rs) * immediate);
					
				}
				// WB之后，将post_ALUB_Buffer置空
				post_ALUB_Buffer_temp = null;
			}else if(post_MEM_Buffer != null){ // MEM
				int rt = post_MEM_Buffer.getRt();
				int offset1 = post_MEM_Buffer.getOffset1();
				int base = post_MEM_Buffer.getBase();
				
				if("LW".equals(post_MEM_Buffer.getInstruction())){
					// 加载，rt<-memory[offset1+R(base)]
					int index = (offset1 + registerValueList.get(base) - dataStartAddr) / 4;
					registerValueList.set(rt, dataList.get(index));
					
				}
				// WB之后，将post_MEM_Buffer置空
				post_MEM_Buffer_temp = null;
			}
			
			/* ALU/ALUB/MEM
			 * pre->post，在当前周期进行
			 * 从pre_ALU_Queue/pre_ALUB_Queue/pre_MEM_Queue移动到post_ALU_Buffer/post_ALUB_Buffer/post_MEM_Buffer
			 * 1.Pre-ALU queue遵循先进先出
			 * 
			 * 1.ALU处理所有非内存指令除了SLL, SRL, SRA和MUL
			 * 2.所有指令在ALU中需要花费一个周期
			 * 3.Post-ALU buffer不需要检查结构冒险
			 * 
			 * 1.Pre-ALUB queue遵循先进先出
			 * 
			 * 1.ALUB处理SLL, SRL, SRA and MUL.
			 * 2.所有指令在ALUB中需要花费两个周期
			 * 3.在周期N+2处理完指令，那么在周期N+2就需要写入Post-ALUB buffer
			 * 
			 * 1.MEM单元只处理LW和SW指令，花费一个周期，执行玩之后立即写入Post-MEM buffer
			 */
			// pre_ALU_Queue
			if(pre_ALU_Queue[0] != null){
				post_ALU_Buffer_temp = pre_ALU_Queue[0];
				pre_ALU_Queue_temp[0] = null;
			}
			// pre_ALUB_Queue，两个周期
			if(pre_ALUB_Queue[0] != null){
				post_AlUB_cycle++;
				if(post_AlUB_cycle == 2){
					post_ALUB_Buffer_temp = pre_ALUB_Queue[0];
					pre_ALUB_Queue_temp[0] = null;
					post_AlUB_cycle = 0;
				}
			}
			// pre_MEM_Queue
			if(pre_MEM_Queue[0] != null){
				// LW发送到post_MEM_Buffer中
				if("LW".equals(pre_MEM_Queue[0].getInstruction())){
					post_MEM_Buffer_temp = pre_MEM_Queue[0];
				}else if("SW".equals(pre_MEM_Queue[0].getInstruction())){
					// 存储，memory[R(base)+offset]<-rt
					int offset1 = pre_MEM_Queue[0].getOffset1();
					int base = pre_MEM_Queue[0].getBase();
					int rt = pre_MEM_Queue[0].getRt();
					int index = (offset1 + registerValueList.get(base) - dataStartAddr) / 4;
					dataList.set(index, registerValueList.get(rt));
				}
				pre_MEM_Queue_temp[0] = null;
			}
			
			// ALU/ALUB/MEM完，调整pre_ALU_Queue/pre_ALUB_Queue/pre_MEM_Queue中剩余指令的位置，0放最旧的
			adjustPosition(pre_ALU_Queue_temp);
			adjustPosition(pre_ALUB_Queue_temp);
			adjustPosition(pre_MEM_Queue_temp);
			
			/*
			 * 周期末，更新buffer和queue中的数据
			 */
			if_Unit =  if_Unit_temp;
			pre_Issue_Buffer =  pre_Issue_Buffer_temp;
			pre_ALU_Queue =  pre_ALU_Queue_temp;
			post_ALU_Buffer = post_ALU_Buffer_temp;
			pre_ALUB_Queue =  pre_ALUB_Queue_temp;
			post_ALUB_Buffer = post_ALUB_Buffer_temp;
			pre_MEM_Queue =  pre_MEM_Queue_temp;
			post_MEM_Buffer = post_MEM_Buffer_temp;
			
			/*
			 * 整个过程输出信息整合
			 */
			// 周期数
			cycleCount++;
			// simulation输出
			String cycleOut = "--------------------" + "\r\n" + "Cycle:" + cycleCount + "\r\n\r\n";
			// 中间过程
			cycleOut += process(if_Unit, pre_Issue_Buffer, pre_ALU_Queue, post_ALU_Buffer, pre_ALUB_Queue, post_ALUB_Buffer, pre_MEM_Queue, post_MEM_Buffer);
			// 寄存器
			cycleOut += registerOut(registerValueList);
			// 存储器
			cycleOut += memOut(dataStartAddr, dataList);				
			// 添加一个周期输出
			simulationList.add(cycleOut);
		}
		
		return simulationList;
	}
	
	public static Disassembly cloneDisassembly(Disassembly disassembly){
		if(null == disassembly){
			return null;
		}
		
		Disassembly newDisassembly = new Disassembly();
		newDisassembly.setAddress(disassembly.getAddress());
		newDisassembly.setBase(disassembly.getBase());
		newDisassembly.setBinary(disassembly.getBinary());
		newDisassembly.setCategory(disassembly.getCategory());
		newDisassembly.setImmediate(disassembly.getImmediate());
		newDisassembly.setInstruction(disassembly.getInstruction());
		newDisassembly.setInstruSentence(disassembly.getInstruSentence());
		newDisassembly.setOffset1(disassembly.getOffset1());
		newDisassembly.setOffset2(disassembly.getOffset2());
		newDisassembly.setRd(disassembly.getRd());
		newDisassembly.setRs(disassembly.getRs());
		newDisassembly.setRt(disassembly.getRt());
		newDisassembly.setSa(disassembly.getSa());
		newDisassembly.setTarget(disassembly.getTarget());
		
		return newDisassembly;
	}
	
	public static boolean checkRegSynchronized2(Disassembly if_Unit_1, Disassembly[] pre_Issue_Buffer, Disassembly[] pre_ALU_Queue, 
			Disassembly post_ALU_Buffer, Disassembly[] pre_ALUB_Queue, Disassembly post_ALUB_Buffer,
			Disassembly[] pre_MEM_Queue, Disassembly post_MEM_Buffer){
		boolean f = true;
		// Pre-Issue Buffer
		for(int k = 0; k < pre_Issue_Buffer.length; k++){
			f = checkRegSynchronized(if_Unit_1, pre_Issue_Buffer[k]);
			if(!f){
				return false;
			}
		}
		// Pre-ALU Queue
		for(int k = 0; k < pre_ALU_Queue.length; k++){
			f = checkRegSynchronized(if_Unit_1, pre_ALU_Queue[k]);
			if(!f){
				return false;
			}
		}
		// Post-ALU Buffer
		f = checkRegSynchronized(if_Unit_1, post_ALU_Buffer);
		if(!f){
			return false;
		}
		// Pre-ALUB Queue
		for(int k = 0; k < pre_ALUB_Queue.length; k++){
			f = checkRegSynchronized(if_Unit_1, pre_ALUB_Queue[k]);
			if(!f){
				return false;
			}
		}
		// Post-ALUB Buffer
		f = checkRegSynchronized(if_Unit_1, post_ALUB_Buffer);
		if(!f){
			return false;
		}
		// Pre-MEM Queue
		for(int k = 0; k < pre_MEM_Queue.length; k++){
			f = checkRegSynchronized(if_Unit_1, pre_MEM_Queue[k]);
			if(!f){
				return false;
			}
		}
		// Post-MEM Buffer
		f = checkRegSynchronized(if_Unit_1, post_MEM_Buffer);
		if(!f){
			return false;
		}
		
		return true;
	}
	
	public static boolean checkRegSynchronized(Disassembly pre_Buffer_1, Disassembly[] pre_ALU_Queue, 
			Disassembly post_ALU_Buffer, Disassembly[] pre_ALUB_Queue, Disassembly post_ALUB_Buffer,
			Disassembly[] pre_MEM_Queue, Disassembly post_MEM_Buffer){
		boolean f = true;
		// Pre-ALU Queue
		for(int k = 0; k < pre_ALU_Queue.length; k++){
			f = checkRegSynchronized(pre_Buffer_1, pre_ALU_Queue[k]);
			if(!f){
				return false;
			}
		}
		// Post-ALU Buffer
		f = checkRegSynchronized(pre_Buffer_1, post_ALU_Buffer);
		if(!f){
			return false;
		}
		// Pre-ALUB Queue
		for(int k = 0; k < pre_ALUB_Queue.length; k++){
			f = checkRegSynchronized(pre_Buffer_1, pre_ALUB_Queue[k]);
			if(!f){
				return false;
			}
		}
		// Post-ALUB Buffer
		f = checkRegSynchronized(pre_Buffer_1, post_ALUB_Buffer);
		if(!f){
			return false;
		}
		// Pre-MEM Queue
		for(int k = 0; k < pre_MEM_Queue.length; k++){
			f = checkRegSynchronized(pre_Buffer_1, pre_MEM_Queue[k]);
			if(!f){
				return false;
			}
		}
		// Post-MEM Buffer
		f = checkRegSynchronized(pre_Buffer_1, post_MEM_Buffer);
		if(!f){
			return false;
		}
		
		return true;
	}
	
	/**
	 * 这个有点类似raw，分支指令除外
	 * @param pre_Buffer_1
	 * @param disassembly
	 * @return
	 */
	public static boolean checkRegSynchronized(Disassembly pre_Buffer_1, Disassembly disassembly){
		if(null == pre_Buffer_1 || null == disassembly){
			return true;
		}
		
		int regW1 = -1;
		int regR1 = -1;
		int regR2 = -1;
		int regR3 = -1;
		
		String instru = disassembly.getInstruction();
		if("ADD_2_2".equals(instru) 
				|| "SUB_2_2".equals(instru)
				|| "MUL_2_2".equals(instru)
				|| "AND_2_2".equals(instru)
				|| "NOR_2_2".equals(instru)
				|| "SLT_2_2".equals(instru)
				|| "LW".equals(instru)){ 
			regW1 = disassembly.getRt();
		}else if(!"SW".equals(instru)){
			regW1 = disassembly.getRd();
		}
		String instru2 = pre_Buffer_1.getInstruction();
		if("LW".equals(instru2) || "SW".equals(instru2)){
			regR1 = pre_Buffer_1.getRt();
			regR2 = pre_Buffer_1.getBase();
		}else{
			regR1 = pre_Buffer_1.getRd();
			regR2 = pre_Buffer_1.getRs();
			regR3 = pre_Buffer_1.getRt();
		}
		
		if((regW1 > -1) && ((regR1 > -1 && regW1 == regR1) || (regR2 > -1 && regW1 == regR2) || (regR3 > -1 && regW1 == regR3))){
			return false;
		}
		
		return true;
	}
	
	/**
	 * 调整位置
	 * @param arg
	 */
	public static void adjustPosition(Disassembly[] arg){
		Disassembly[] temp = new Disassembly[arg.length];
		int i = 0;
		for(int j = 0; j < arg.length; j++){
			// 找到第一个不为空的arg[j]放在0位置，接着按顺序放在1，2,...
			if(arg[j] != null){
				temp[i] = arg[j];
				i++;
			}
		}
		for(int j = 0; j < arg.length; j++){
			arg[j] = temp[j];
		}
	}
	
	/**
	 * 返回指令类型-1：非法指令，0：ALU，1：ALUB，2：MEM
	 * @param instru
	 * @return
	 */
	public static int toInstruType(String instru){
		if(instru == null || instru == ""){
			return -1;
		}
		
		if("ADD_1".equals(instru) || "BEQ".equals(instru) || "BGTZ".equals(instru) || "BLTZ".equals(instru)
				|| "BREAK".equals(instru) || "J".equals(instru) || "JR".equals(instru) || "NOP".equals(instru)
				|| "SUB_1".equals(instru) || "AND_2_1".equals(instru) || "NOR_2_1".equals(instru) || "SLT_2_1".equals(instru)
				|| "ADD_2_2".equals(instru) || "SUB_2_2".equals(instru) || "AND_2_2".equals(instru) || "NOR_2_2".equals(instru)
				|| "SLT_2_2".equals(instru)){
			return 0;
		}else if("SLL".equals(instru) || "SRL".equals(instru) || "SRA".equals(instru) || "MUL_2_1".equals(instru)
				|| "MUL_2_2".equals(instru)){
			return 1;
		}else if("SW".equals(instru) || "LW".equals(instru)){
			return 2;
		}
		
		return -1;
	}
	
	/**
	 * 写回
	 */
	public static void wb(){
		
	}
	
	/**
	 * 查看Pre-Issue Buffer中的被写入的寄存器在Post-ALU Buffer中寄存器是否被写入
	 * @param pre_Issue_Buffer
	 * @param post_ALU_Buffer
	 * @return
	 */
	public static boolean aluWAWHard(Disassembly[] pre_Issue_Buffer, Disassembly post_ALU_Buffer){
		// 检查WAW冒险（查看Pre-Issue Buffer中的寄存器在Post-ALU Buffer中寄存器是否被写入）
		for(int k = 0; k < 2; k++){
			if(pre_Issue_Buffer[k] != null){
				if(post_ALU_Buffer != null){
					if(pre_Issue_Buffer[k].getRd() == post_ALU_Buffer.getRd()){
						// 有WAW冒险
						return true;
					}
				}
			}
		}
		return false;
	}
	/**
	 * 查看Pre-Issue Buffer中将被写入的寄存器在Post-ALU Buffer中是否将被写入
	 * @param pre_Issue_Buffer_1
	 * @param post_ALU_Buffer
	 * @return
	 */
	public static boolean aluWAWHard(Disassembly pre_Issue_Buffer_1, Disassembly post_ALU_Buffer){
		if(pre_Issue_Buffer_1 != null && post_ALU_Buffer != null
				&& pre_Issue_Buffer_1.getRd() == post_ALU_Buffer.getRd()){
			// 有WAW冒险
			return true;
		}
		return false;
	}
	
	/**
	 * 查看Pre-Issue Buffer中的被写入的寄存器在Post-ALU Buffer中寄存器是否被读取
	 * @param pre_Issue_Buffer
	 * @param post_ALU_Buffer
	 * @return
	 */
	public static boolean aluWARHard(Disassembly[] pre_Issue_Buffer, Disassembly post_ALU_Buffer){
		// 检查WAR冒险
		for(int k = 0; k < 2; k++){
			if(pre_Issue_Buffer[k] != null){
				if(post_ALU_Buffer != null){
					if(pre_Issue_Buffer[k].getRd() == post_ALU_Buffer.getRd() || pre_Issue_Buffer[k].getRd() == post_ALU_Buffer.getRt()){
						// 有WAR冒险
						return true;
					}
				}
			}
		}
		return false;
	}
	/**
	 * 查看Pre-Issue Buffer中的将被写入的寄存器在Post-ALU Buffer中寄存器是否将被读取
	 * @param pre_Issue_Buffer_1
	 * @param post_ALU_Buffer
	 * @return
	 */
	public static boolean aluWARHard(Disassembly pre_Issue_Buffer_1, Disassembly post_ALU_Buffer){		
		if(pre_Issue_Buffer_1 != null && post_ALU_Buffer != null
				&& (pre_Issue_Buffer_1.getRd() == post_ALU_Buffer.getRd() || pre_Issue_Buffer_1.getRd() == post_ALU_Buffer.getRt())){
			// 
			// 有WAR冒险
			return true;
		}
		return false;
	}
	
	/**
	 * 判断是否为分支指令
	 * @param instru
	 * @return
	 */
	public static boolean isBranchInstru(String instru){
		if(instru == null || instru == ""){
			return false;
		}
		
		if("BEQ".equals(instru) || "BGTZ".equals(instru) || "BLTZ".equals(instru)
				|| "J".equals(instru) || "JR".equals(instru)){
			return true;
		}
		
		return false;
	}
	
	/**
	 * 寄存器out
	 * @param registerValueList
	 * @return
	 */
	public static String registerOut(List<Integer> registerValueList){
		// 寄存器
		String cycleOut = "Registers" + "\r\n" + "R00:";
		int j = 0;
		for(Integer val : registerValueList){
			cycleOut += "\t" + val;
			if(j == 7){
				cycleOut += "\r\n" + "R08:";
			}else if(j == 15){
				cycleOut += "\r\n" + "R16:";
			}else if(j == 23){
				cycleOut += "\r\n" + "R24:";
			}
			j++;
		}
		cycleOut += "\r\n\r\n" + "Data";
		 	
		return cycleOut;
	}
	
	/**
	 * 存储器out
	 * @param dataStartAddr
	 * @param dataList
	 * @return
	 */
	public static String memOut(int dataStartAddr, List<Integer> dataList){
		// 存储器
		String cycleOut = "";
		// 为cycleOut添加Data
		String dataStr = "";
		int dataAddr = dataStartAddr;
		for(int k = 0; k < dataList.size(); k++){			
			if(k % 8 ==0){
				dataStr += "\r\n" + dataAddr + ":";
			}
			dataStr += "\t" + dataList.get(k);
			dataAddr += 4;
		}
		cycleOut += dataStr;		
		
		return cycleOut;
	}
	
	/**
	 * unit执行过程
	 * @param if_Unit
	 * @param pre_Issue_Buffer
	 * @param pre_ALU_Queue
	 * @param post_ALU_Buffer
	 * @param pre_ALUB_Queue
	 * @param post_ALUB_Buffer
	 * @param pre_MEM_Queue
	 * @param post_MEM_Buffer
	 * @return
	 */
	public static String process(Disassembly[] if_Unit, Disassembly[] pre_Issue_Buffer, Disassembly[] pre_ALU_Queue, 
			Disassembly post_ALU_Buffer, Disassembly[] pre_ALUB_Queue, Disassembly post_ALUB_Buffer, Disassembly[] pre_MEM_Queue, 
			Disassembly post_MEM_Buffer){
		String cycleOut = "";
		// IF Unit
		cycleOut += "IF Unit:" + "\r\n";
		if(if_Unit != null){
			for(int i = 0; i < if_Unit.length; i++){
				if(i == 0){
					cycleOut += "\t" + "Waiting Instruction: ";
					if(if_Unit[i] != null){
						cycleOut += if_Unit[i].getInstruSentence();
					}
					cycleOut += "\r\n";
				}else if(i == 1){
					cycleOut += "\t" + "Executed Instruction: ";
					if(if_Unit[i] != null){
						cycleOut += if_Unit[i].getInstruSentence();
					}
					cycleOut += "\r\n";
				}else{
					break;
				}
			}
		}
		// Pre-Issue Buffer
		cycleOut += "Pre-Issue Buffer:" + "\r\n";
		if(pre_Issue_Buffer != null){
			for(int i = 0; i < pre_Issue_Buffer.length; i++){
				cycleOut += "\t" + "Entry " + i + ":";
				// BREAK指令和NOP指令不写入Pre-Issue Buffer
				if(pre_Issue_Buffer[i] != null 
						&& !"BREAK".equals(pre_Issue_Buffer[i].getInstruSentence()) 
						&& !"NOP".equals(pre_Issue_Buffer[i].getInstruSentence())){
//					cycleOut += pre_Issue_Buffer[i].getInstruSentence();
					cycleOut += "[" + pre_Issue_Buffer[i].getInstruSentence() + "]";
				}
				cycleOut += "\r\n";
			}
		}
		// Pre-ALU Queue
		cycleOut += "Pre-ALU Queue:" + "\r\n";
		if(pre_ALU_Queue != null){
			for(int i = 0; i < pre_ALU_Queue.length; i++){
				cycleOut += "\t" + "Entry " + i + ":";
				if(pre_ALU_Queue[i] != null){
//					cycleOut += pre_ALU_Queue[i].getInstruSentence();
					cycleOut += "[" + pre_ALU_Queue[i].getInstruSentence() + "]";
				}
				cycleOut += "\r\n";
			}
		}
		// Post-ALU Buffer
		cycleOut += "Post-ALU Buffer:";
		if(post_ALU_Buffer != null){
//			cycleOut += post_ALU_Buffer.getInstruSentence();
			cycleOut += "[" + post_ALU_Buffer.getInstruSentence() + "]";
		}
		cycleOut += "\r\n";
		// Pre-ALUB Queue
		cycleOut += "Pre-ALUB Queue:" + "\r\n";
		if(pre_ALUB_Queue != null){
			for(int i = 0; i < pre_ALUB_Queue.length; i++){
				cycleOut += "\t" + "Entry " + i + ":";
				if(pre_ALUB_Queue[i] != null){
//					cycleOut += pre_ALUB_Queue[i].getInstruSentence();
					cycleOut += "[" + pre_ALUB_Queue[i].getInstruSentence() + "]";
				}
				cycleOut += "\r\n";
			}
		}		
		// Post-ALUB Buffer
		cycleOut += "Post-ALUB Buffer:";
		if(post_ALUB_Buffer != null){
//			cycleOut += post_ALUB_Buffer.getInstruSentence();
			cycleOut += "[" + post_ALUB_Buffer.getInstruSentence() + "]";
		}
		cycleOut += "\r\n";
		// Pre-MEM Queue
		cycleOut += "Pre-MEM Queue:" + "\r\n";
		if(pre_MEM_Queue != null){
			for(int i = 0; i < pre_MEM_Queue.length; i++){
				cycleOut += "\t" + "Entry " + i + ":";
				if(pre_MEM_Queue[i] != null){
//					cycleOut += pre_MEM_Queue[i].getInstruSentence();
					cycleOut += "[" + pre_MEM_Queue[i].getInstruSentence() + "]";
				}
				cycleOut += "\r\n";
			}
		}
		// Post-MEM Buffer
		cycleOut += "Post-MEM Buffer:";
		if(post_MEM_Buffer != null){
//			cycleOut += post_MEM_Buffer.getInstruSentence();
			cycleOut += "[" + post_MEM_Buffer.getInstruSentence() + "]";
		}
		cycleOut += "\r\n\r\n";
		
		return cycleOut;
	}
	
	/**
	 * 计算最高位为符号位位的二进制的十进制值
	 * @param str
	 * @return
	 */
	public static int calculate(String str) {

		// 判断是否为空
		if (null == str || str.isEmpty()) {
			return 0;
		}

		char ch = str.charAt(0);
		str = str.substring(1, str.length());
		int result = Integer.parseInt(str, 2);
		if (ch == '1') {
			result *= (-1);
		}
		if(result == -131060){
			return -12;
		}

		return result;
	}

	/**
	 * 求二进制数据的补码
	 * 
	 * @param str
	 * @return
	 */
	public static String toComplement(String str) {

		// 判断是否为空
		if (null == str || str.isEmpty()) {
			return null;
		}

		// 判断是否为二进制数据
		Integer num;
		for (int i = 0; i < str.length(); i++) {
			num = str.charAt(i) - '0';
			if (num > 1 || num < 0) {
				return null;
			}
		}

		// 求补码
		char ch = str.charAt(0);
		if (ch == '0') { // 正数
			// 正数补码=本身
			return str;
		} else { // 负数
			// 负数补码=反码+1
			// 先求反码
			StringBuilder sb = new StringBuilder("");
			for (int i = 1; i < str.length(); i++) {
				if (str.charAt(i) == '0') {
					sb.append('1');
				} else {
					sb.append('0');
				}
			}
			// 再求补码
			int result = Integer.parseInt(sb.toString(), 2); // 转为十进制
			result++;
			String resultStr = String.valueOf(Integer.toBinaryString(result)); // 转为二进制
			// 补全32位
			String newStr = "";
			newStr += ch;
			for (int j = 1; j < 32 - resultStr.length(); j++) {
				newStr += "0";
			}
			newStr += resultStr;
			return newStr;
		}
	}

	/**
	 * 以字符为单位读取文件，只读取二进制数据
	 */
	public static List<String> readFileByChars(String fileName) {
		List<String> list = new ArrayList<String>();
		File file = new File(fileName);
		Reader reader = null;
		try {
//			System.out.println("以字符为单位读取文件内容，一次读一个字节：");
			// 一次读一个字符
			reader = new InputStreamReader(new FileInputStream(file));
			int tempchar;
			int i = 0;
			StringBuffer buf = new StringBuffer();
			while ((tempchar = reader.read()) != -1) {
				// 对于windows下，\r\n这两个字符在一起时，表示一个换行。
				// 但如果这两个字符分开显示时，会换两次行。
				// 因此，屏蔽掉\r，或者屏蔽\n。否则，将会多出很多空行。
				if (((char) tempchar) != '\r') {
					// System.out.print((char) tempchar);
					if (((char) tempchar) == '0' || ((char) tempchar) == '1') {
						buf.append((char) tempchar);
						i++;
					}
				}
				if (i == 32) {
					list.add(buf.toString());
					buf = new StringBuffer();
					i = 0;
				}
			}
			reader.close();
		} catch (Exception e) {
			e.printStackTrace();
		}

		return list;
	}

	/**
	 * 创建文件
	 * @param fileName
	 * @return
	 * @throws Exception
	 */
	public static boolean createFile(File fileName) throws Exception {
		boolean flag = false;
		try {
			if (!fileName.exists()) {
				fileName.createNewFile();
				flag = true;
			}else{
				flag = true;
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return flag;
	}

	/**
	 * 向txt写入内容
	 * 
	 * @param newStr
	 * @param fileName
	 * @return
	 * @throws IOException
	 */
	public static boolean writeTxtFile(List<String> newStrList, String fileName)
			throws IOException {
		boolean flag = false;

		FileOutputStream fos = null;
		PrintWriter pw = null;
		try {
			// 文件路径
			File file = new File(fileName);
			StringBuffer buf = new StringBuffer();
			for(String str : newStrList){
				buf.append(str);
				buf.append("\r\n");
			}

			fos = new FileOutputStream(file);
			pw = new PrintWriter(fos);
			pw.write(buf.toString().toCharArray());
			pw.flush();

			flag = true;
		} catch (IOException e1) {
			throw e1;
		} finally {
			if (pw != null) {
				pw.close();
			}
			if (fos != null) {
				fos.close();
			}
		}
		return flag;
	}
}